package com.naiterui.ehp.bs.doctor.service.impl;

import cn.hutool.core.util.StrUtil;
import com.naiterui.common.redis.RedisUtil;
import com.naiterui.ehp.bp.domain.Doctor;
import com.naiterui.ehp.bp.domain.Licence;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bs.doctor.exception.ExceptionCodes;
import com.naiterui.ehp.bs.doctor.fegin.EsignFeginClient;
import com.naiterui.ehp.bs.doctor.repository.IDoctorRepository;
import com.naiterui.ehp.bs.doctor.service.ITencentDetectService;
import com.naiterui.ehp.bs.doctor.service.user.ILicenceService;
import com.naiterui.ehp.bs.doctor.utils.AdTencentCloudSdkUtil;
import com.naiterui.ehp.bs.doctor.utils.PropertyValueConstants;
import com.naiterui.ehp.bs.doctor.vo.TencentFaceIdVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.util.UUID;

/**
 * @author guoyongxiang
 * @date 2019/10/19 10:31
 * @since 1.0.0
 */
@Slf4j
@Service
public class AdTencentDetectServiceImpl implements ITencentDetectService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AdTencentDetectServiceImpl.class);

    /**
     * 腾讯云人脸识别orderNo
     */
    private static final String RDS_TENCENT_ORDER_NO = PropertyValueConstants.RDS_DETECT + "orderNo_";

    private static final String H5_RDS_TENCENT_ORDER_NO = PropertyValueConstants.RDS_DETECT + "h5_orderNo_";

    private static final String H5_RDS_TENCENT_RESULT = PropertyValueConstants.RDS_DETECT + "h5_result_";

    private static final String USER_ID_PRE = "DR";
    /**
     * 腾讯云人脸识别状态缓存有效期(秒)
     */
    private static final Integer RDS_TENCENT_CACHE_EXPIRE_SECOND = 60 * 5;

    @Value("${tencent-cloud.ad.callback}")
    private String callbackUrl;
    @Value("${pcH5_meta}")
    private String pcH5Domain;

    @Autowired
    private IDoctorRepository doctorRepository;
    @Autowired
    private ILicenceService licenceService;
    @Autowired
    private EsignFeginClient esignFeginClient;

    @Override
    public TencentFaceIdVO getFaceId(Long doctorId) throws BusinessException {
        Licence licence = licenceService.getLicenceByType(doctorId, Licence.DOCTOR_LICENCE_TYPE_IDCARD);
        // 验证该身份证号是否已有实名
        esignFeginClient.checkDoctorRealname(doctorId, licence.getNumber());
        return this.getFaceId(doctorId, licence.getNumber());
    }

    @Override
    public TencentFaceIdVO getH5FaceId(String userId, String idNo, String name)
            throws BusinessException, UnsupportedEncodingException {

        if (StringUtils.isBlank(idNo) || StringUtils.isBlank(name)) {
            log.warn("当前用户实名信息未填写完整 name:{}", name);
            throw new BusinessException(com.naiterui.ehp.bs.patient.exception.ExceptionCodes.INVALID_REQUEST, "当前用户实名信息未填写完整");
        }

        String orderNo = UUID.randomUUID().toString().replaceAll("-", "");
        RedisUtil.valueOps().set(H5_RDS_TENCENT_ORDER_NO + userId, orderNo, RDS_TENCENT_CACHE_EXPIRE_SECOND);
        TencentFaceIdVO faceIdVO = AdTencentCloudSdkUtil.getH5Faceid(orderNo, name, idNo, userId);
        // 获取H5人脸识别地址
        String h5url = AdTencentCloudSdkUtil.getFaceH5LoginUrl(orderNo, faceIdVO.getH5faceId(), userId, callbackUrl, faceIdVO.getOptimalDomain());
        faceIdVO.setH5faceUrl(h5url);
        return faceIdVO;
    }


    @Override
    public TencentFaceIdVO getFaceId(Long doctorId, String idNo) throws BusinessException {
        Doctor doctor = doctorRepository.get(doctorId);
        if (StringUtils.isBlank(idNo) || StringUtils.isBlank(doctor.getName())) {
            LOGGER.warn("当前用户实名信息未填写完整 name:{}", doctor.getName());
            throw new BusinessException(ExceptionCodes.INVALID_REQUEST, "当前用户实名信息未填写完整");
        }

        String orderNo = UUID.randomUUID().toString().replaceAll("-", "");
        RedisUtil.valueOps().set(RDS_TENCENT_ORDER_NO + doctor.getId(), orderNo, RDS_TENCENT_CACHE_EXPIRE_SECOND);
        idNo = idNo.replace("*", "X");
        return AdTencentCloudSdkUtil.getFaceid(orderNo, doctor.getName(), idNo, USER_ID_PRE + doctorId);
    }

    @Override
    public AdTencentCloudSdkUtil.FaceSyncVO getFaceSync(Long doctorId) throws BusinessException {
        String orderNo = RedisUtil.valueOps().getString(RDS_TENCENT_ORDER_NO + doctorId);
        RedisUtil.keyOps().delete(RDS_TENCENT_ORDER_NO + doctorId);
        if (StringUtils.isBlank(orderNo)) {
            return AdTencentCloudSdkUtil.FaceSyncVO.builder().result(false).build();
        }

        AdTencentCloudSdkUtil.FaceSyncVO faceSyncVO = AdTencentCloudSdkUtil.getFaceidSync(orderNo, USER_ID_PRE + doctorId);
        if (faceSyncVO.getResult()) {
            LOGGER.info("腾讯云人脸实名认证成功,设置进度状态 doctorId:{}", doctorId);
        }
        return faceSyncVO;
    }

    @Override
    public AdTencentCloudSdkUtil.FaceSyncVO getH5FaceSync(Long doctorId) throws BusinessException {
        String orderNo = RedisUtil.valueOps().getString(H5_RDS_TENCENT_ORDER_NO + doctorId);
        RedisUtil.keyOps().delete(H5_RDS_TENCENT_ORDER_NO + doctorId);
        if (StringUtils.isBlank(orderNo)) {
            return AdTencentCloudSdkUtil.FaceSyncVO.builder().result(false).build();
        }

        AdTencentCloudSdkUtil.FaceSyncVO faceSyncVO = AdTencentCloudSdkUtil.getH5FaceidSync(orderNo, USER_ID_PRE + doctorId);
        if (faceSyncVO.getResult()) {
            LOGGER.info("腾讯云人脸实名认证成功,设置进度状态 doctorId:{}", doctorId);
        }
        return faceSyncVO;
    }

    @Override
    public String callbackH5Redirect(String code, String orderNo, String h5faceId, String newSignature, String liveRate) {
        if (AdTencentCloudSdkUtil.CODE_SUCCESS.equals(code)) {
            log.info("腾讯云人脸识别完成 code {}, orderNo {}, h5faceId {}, newSignature {},liveRate {}", code, orderNo, h5faceId, newSignature, liveRate);
            RedisUtil.valueOps().setEx(H5_RDS_TENCENT_RESULT + h5faceId, AdTencentCloudSdkUtil.CODE_SUCCESS, 60 * 6);
        } else {
            RedisUtil.valueOps().setEx(H5_RDS_TENCENT_RESULT + h5faceId, "-1", 60 * 6);
        }
        return pcH5Domain + "/login/success";
    }

    public static String addUrlParam(String url, String name, String value) {
        String mark = !StrUtil.containsAny(url, "?") ? "?" : "&";
        return url + mark + name + "=" + value;
    }
}
